package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.annotation.PromiseStyleMinVersion
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.Promise

////////////////////
// Management
////////////////////
/**
 * The `Browser.management` API provides ways to manage installed apps and extensions.
 *
 * Permissions: "management"
 */
interface Management {
    // Display options to create shortcuts for an app. On Mac, only packaged app shortcuts can be created.
    @PromiseStyleMinVersion(88)
     fun createAppShortcut(
        // This should be the id from an app item of management.ExtensionInfo.
        id: String,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Generate an app for a URL. Returns the generated bookmark app.
    @PromiseStyleMinVersion(88)
     fun generateAppForLink(
        // The URL of a web page. The scheme of the URL can only be "http" or "https".
        url: String,
        // The title of the generated app.
        title: String,
        callback: Value1Function<ExtensionInfo>? = null
    ): Promise<ExtensionInfo>

    // Returns information about the installed extension, app, or theme that has the given ID.
    @PromiseStyleMinVersion(88)
     fun get(
        // The ID from an item of management.ExtensionInfo.
        id: String,
        callback: Value1Function<ExtensionInfo>? = null
    ): Promise<ExtensionInfo>

    // Returns a list of information about installed extensions and apps.
    @PromiseStyleMinVersion(88)
     fun getAll(
        callback: Value1Function<List<ExtensionInfo>>? = null
    ): Promise<List<ExtensionInfo>>

    // Returns a list of permission warnings for the given extension id.
    @PromiseStyleMinVersion(88)
     fun getPermissionWarningsById(
        // The ID of an already installed extension.
        id: String,
        callback: Value1Function<List<String>>? = null
    ): Promise<List<String>>

    // Returns a list of permission warnings for the given extension manifest string.
    // Note: This function can be used without requesting the 'management' permission in the manifest.
    @PromiseStyleMinVersion(88)
     fun getPermissionWarningsByManifest(
        // Extension manifest JSON string.
        manifestStr: String,
        callback: Value1Function<List<String>>? = null
    ): Promise<List<String>>

    // Returns information about the calling extension, app, or theme.
    // Note: This function can be used without requesting the 'management' permission in the manifest.
    @PromiseStyleMinVersion(88)
     fun getSelf(
        callback: Value1Function<ExtensionInfo>? = null
    ): Promise<ExtensionInfo>

    // Launches the replacement_web_app specified in the manifest.
    // Prompts the user to install if not already installed.
    @ChromeMinVersion(77)
    @PromiseStyleMinVersion(88)
     fun installReplacementWebApp(
        callback: VoidFunction? = null
    ): Promise<Void>

    // Launches an application.
    @PromiseStyleMinVersion(88)
     fun launchApp(
        // The extension id of the application.
        id: String,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Enables or disables an app or extension.
    // In most cases this function must be called in the context of a user gesture (e.g. an onclick handler for a button),
    // and may present the user with a native confirmation UI as a way of preventing abuse.
    @PromiseStyleMinVersion(88)
     fun setEnabled(
        // This should be the id from an item of management.ExtensionInfo.
        id: String,
        // Whether this item should be enabled or disabled.
        enabled: Boolean,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Set the launch type of an app.
    @PromiseStyleMinVersion(88)
     fun setLaunchType(
        // This should be the id from an app item of management.ExtensionInfo.
        id: String,
        // The target launch type. Always check and make sure this launch type is in ExtensionInfo.availableLaunchTypes,
        // because the available launch types vary on different platforms and configurations.
        launchType: LaunchType,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Uninstalls a currently installed app or extension.
    // Note: This function does not work in managed environments when the user is not allowed to uninstall the specified extension/app.
    // If the uninstall fails (e.g. the user cancels the dialog) the promise will be rejected or the callback will be called with runtime.lastError set.
    @PromiseStyleMinVersion(88)
     fun uninstall(
        // This should be the id from an item of management.ExtensionInfo.
        id: String,
        options: UninstallOptions?,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Uninstalls the calling extension.
    // Note: This function can be used without requesting the 'management' permission in the manifest.
    // This function does not work in managed environments when the user is not allowed to uninstall the specified extension/app.
    @PromiseStyleMinVersion(88)
     fun uninstallSelf(
        options: UninstallOptions?,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Fired when an app or extension has been disabled.
     val onDisabled: Events.Event<Value1Function<ExtensionInfo>>

    // Fired when an app or extension has been enabled.
     val onEnabled: Events.Event<Value1Function<ExtensionInfo>>

    // Fired when an app or extension has been installed.
     val onInstalled: Events.Event<Value1Function<ExtensionInfo>>

    // Fired when an app or extension has been uninstalled.
     val onUninstalled: Events.Event<Value1Function<String>>

    // A reason the item is disabled.
    @ChromeMinVersion(44)
    enum class ExtensionDisabledReason {
        unknown,
        permissions_increase
    }

    // Information about an installed extension, app, or theme.
    data class ExtensionInfo(
        // The launch url (only present for apps).
        var appLaunchUrl: String?,
        // The currently available launch types (only present for apps).
        var availableLaunchTypes: List<LaunchType>?,
        // The description of this extension, app, or theme.
        var description: String,
        // A reason the item is disabled.
        var disabledReason: ExtensionDisabledReason?,
        // Whether it is currently enabled or disabled.
        var enabled: Boolean,
        // The URL of the homepage of this extension, app, or theme.
        var homepageUrl: String?,
        // Returns a list of host based permissions.
        var hostPermissions: List<String>,
        // A list of icon information. Note that this just reflects what was declared in the manifest,
        // and the actual image at that url may be larger or smaller than what was declared,
        // so you might consider using explicit width and height attributes on img tags referencing these images.
        // See the manifest documentation on icons for more details.
        var icons: List<IconInfo>?,
        // The extension's unique identifier.
        var id: String,
        // How the extension was installed.
        var installType: ExtensionInstallType,
        // True if this is an app.
        @Deprecated(
            "Deprecated",
            replaceWith = ReplaceWith("Please use management.ExtensionInfo.type.")
        )
        var isApp: Boolean,
        // The app launch type (only present for apps).
        var launchType: LaunchType?,
        // Whether this extension can be disabled or uninstalled by the user.
        var mayDisable: Boolean,
        // Whether this extension can be enabled by the user. This is only returned for extensions which are not enabled.
        @ChromeMinVersion(62)
        var mayEnable: Boolean?,
        // The name of this extension, app, or theme.
        var name: String,
        // Whether the extension, app, or theme declares that it supports offline.
        var offlineEnabled: Boolean,
        // The url for the item's options page, if it has one.
        var optionsUrl: String,
        // Returns a list of API based permissions.
        var permissions: List<String>,
        // A short version of the name of this extension, app, or theme.
        var shortName: String,
        // The type of this extension, app, or theme.
        var type: ExtensionType,
        // The update URL of this extension, app, or theme.
        var updateUrl: String?,
        // The version of this extension, app, or theme.
        var version: String,
        // The version name of this extension, app, or theme if the manifest specified one.
        @ChromeMinVersion(50)
        var versionName: String?,
    )

    // How the extension was installed. One of admin: The extension was installed because of an administrative policy,
    // development: The extension was loaded unpacked in developer mode, normal: The extension was installed normally via a .crx file,
    // sideload: The extension was installed by other software on the machine,
    // other: The extension was installed by other means.
    @ChromeMinVersion(44)
    enum class ExtensionInstallType {
        admin,
        development,
        normal,
        sideload,
        other
    }

    // The type of this extension, app, or theme.
    @ChromeMinVersion(44)
    enum class ExtensionType {
        extension,
        hosted_app,
        packaged_app,
        legacy_packaged_app,
        theme,
        login_screen_extension
    }

    // Information about an icon belonging to an extension, app, or theme.
    data class IconInfo(
        // A number representing the width and height of the icon.
        // Likely values include (but are not limited to) 128, 48, 24, and 16.
        var size: Number,
        // The URL for this icon image.
        // To display a grayscale version of the icon (to indicate that an extension is disabled, for example),
        // append ?grayscale=true to the URL.
        var url: String,
    )

    // These are all possible app launch types.
    enum class LaunchType {
        OPEN_AS_REGULAR_TAB,
        OPEN_AS_PINNED_TAB,
        OPEN_AS_WINDOW,
        OPEN_FULLSCREEN,
    }

    // Options for how to handle the extension's uninstallation.
    @ChromeMinVersion(88)
    data class UninstallOptions(
        // Whether or not a confirm-uninstall dialog should prompt the user.
        // Defaults to false for self uninstalls.
        // If an extension uninstalls another extension,
        // this parameter is ignored and the dialog is always shown.
        var showConfirmDialog: Boolean,
    )
}